package com.cmdi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cmdi.constant.CommonConstants;
import com.cmdi.domain.R;
import com.cmdi.exception.CustomCmdiAdminException;
import com.cmdi.feign.RemoteGatewayServiceFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URI;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmdi.domain.SysRouteConf;
import com.cmdi.mapper.SysRouteConfMapper;
import com.cmdi.service.SysRouteConfService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

@Slf4j
@Service
public class SysRouteConfServiceImpl extends ServiceImpl<SysRouteConfMapper, SysRouteConf> implements SysRouteConfService{
    @Value("${gw.key:abcd}")
    private String key;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RemoteGatewayServiceFeignClient remoteGatewayServiceFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(RouteDefinition route) throws CustomCmdiAdminException{
        SysRouteConf entity = new SysRouteConf();
        entity.setRouteId(route.getId());
        entity.setOrder(route.getOrder());
        entity.setDelFlag("0");
        entity.setUri(route.getUri().toString());
        entity.setPredicates(JSON.toJSONString(route.getPredicates()));
        entity.setFilters(JSON.toJSONString(route.getFilters()));
        Boolean res = false;
        try {
            boolean save = this.save(entity);
            redisTemplate.opsForHash().put(CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS, route.getId(), JSONObject.toJSONString(route));
            //System.out.println( 1 / 0);
            res = true;
        } catch (Exception e) {
            redisTemplate.opsForHash().delete(CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS, route.getId());
            log.error("保存路由错误", e);
            throw new CustomCmdiAdminException(e.getMessage());
        }
        if(res) {
            updateRoute();
        }
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(String routeId) throws CustomCmdiAdminException {
        QueryWrapper<SysRouteConf> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("route_id", routeId).eq("del_flag", 0);
        SysRouteConf one = this.getOne(queryWrapper);
        if(one == null) {
            log.error("路由id={}不存在", routeId);
            return false;
        }

        Boolean res = false;
        try {
            Long delete = redisTemplate.opsForHash().delete(CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS, routeId);
            if(delete > 0) {
                res = this.remove(queryWrapper);
            }
            //System.out.println(1/0);
            updateRoute();
        } catch (Exception e) {
            updateRoute();
            log.error("删除路由id={}错误", e);
            throw new CustomCmdiAdminException(e.getMessage());
        }

        return res;
    }

    @Override
    public Boolean flush() throws CustomCmdiAdminException {
        QueryWrapper<SysRouteConf> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", "0");
        redisTemplate.delete(CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS);
        for (SysRouteConf sysRouteConf : this.list(queryWrapper)) {
            RouteDefinition routeDefinition = new RouteDefinition();

            routeDefinition.setId(sysRouteConf.getRouteId());
            routeDefinition.setOrder(sysRouteConf.getOrder());
            routeDefinition.setUri(URI.create(sysRouteConf.getUri()));

            JSONArray ps = JSONArray.parseArray(sysRouteConf.getPredicates());
            List<PredicateDefinition> predicateDefinitions = ps.toJavaList(PredicateDefinition.class);
            routeDefinition.setPredicates(predicateDefinitions);

            JSONArray fs = JSONArray.parseArray(sysRouteConf.getFilters());
            List<FilterDefinition> filterDefinitions = fs.toJavaList(FilterDefinition.class);
            routeDefinition.setFilters(filterDefinitions);

            redisTemplate.opsForHash().put(CommonConstants.GATEWAY_DYNAMIC_ROUTE_REDIS, routeDefinition.getId(), JSONObject.toJSONString(routeDefinition));

        }
        this.updateRoute();
        return true;
    }

    /**
     * @Description: gateway服务端会校验gw.key，成功后更新路由信息
     * @Author: gaozb
     **/
    public void updateRoute() {
        log.info("正在更新路由");
        ResponseEntity<Boolean> booleanResponseEntity = remoteGatewayServiceFeignClient.updateRoute(key);
    }
}
